export type BlockCallback<T> = (value?: T | undefined) => void;

export type BlockCallbackNULL<T> = BlockCallback<T> | undefined;

export default class Blockutils<T = any> {

    /** 阻塞信号量 */
    private count: number = 0;

    /** 线程锁回调 */
    private backcall: [BlockCallback<T>, BlockCallbackNULL<T>][] = [];

    /** 正在阻塞 */
    public get IsBlockUp() {
        return this.backcall.length > 0;
    }

    /** 阻塞线程 */
    public async Wait(startCall?: () => Promise<void>, endCall?: BlockCallback<T>): Promise<T | undefined> {
        return new Promise(async (res) => {
            this.backcall.push([res, endCall]);
            this.count++;
            if (startCall !== undefined) {
                await startCall();
            }
        });
    }

    /** 释放阻塞信号 */
    public Release(value?: T): void {
        this.count--;
        if (this.count === 0) {
            for (const [call, endCall] of this.backcall) {
                if (endCall) {
                    endCall(value);
                }
                call(value);
            }
            this.backcall = [];
        }
    }
}